﻿using ProjectScheduling.daos;
using ProjectScheduling.models;
using System.Data;

namespace ProjectScheduling
{
    public partial class AddProjectForm : Form
    {
        public readonly static AddProjectForm b = new();
        public Action? ok_action;
        private List<RestDay> restdays = [];
        private List<string> months = [];
        private List<string> days = [];
        public bool isEdit = true;
        public List<(int id, string name)> _project_types = [];
        private bool isLock = false;
        /// <summary>
        /// 构造函数
        /// </summary>
        public AddProjectForm()
        {
            InitializeComponent();
            // 选择员工回调函数

            CheckUsedStaffForm.b.action_checked = (items) =>
            {
                BaseData.Staffs = items;
                var text = string.Join("、", items.Select(lt => lt.name));
                lb_users.Text = text;
            };
            // 选择项目类型回调函数
            CheckProjectTypeForm.b.action = ((int id, string name, int timehours) data) =>
            {
                BaseData.ProjectTypeId = data.id;
                BaseData.ProjectTypeMessage = data;
            };

        }
        private Projects BaseData = new();
        public void InitData(int id)
        {
            BaseData = ProjectDao.Base.Find(id) ?? new();
            _project_types = ProjectTypeDao.Base.FindAll(it => true).Select(it => (it.Id, it.Name ?? "")).ToList();
            txt_type.Items.Clear();
            txt_type.Items.AddRange(_project_types.Select(it => it.name).ToArray());
            if (id == 0)
            {
                BaseData.Staffs = [];
                BaseData.ProjectTypeMessage = (0, "", 0);
                BaseData.FromDate = DateTime.Today;
                BaseData.ToDate = DateTime.Today;
                
                txt_type.SelectedIndex = -1;
            }
            else
            {
                BaseData.Staffs = ProjectStaffDao.Base.FindAll(it => it.ProjectId == id).Select(it => (it.UserId, it.UserName ?? "")).ToList();
                var t = ProjectTypeDao.Base.Find(BaseData.ProjectTypeId);
                BaseData.ProjectTypeMessage = (t.Id, t.Name ?? "", t.StandardWorkingHours);
                isLock = true;
                txt_type.SelectedIndex = _project_types.FindIndex(it => it.name == t.Name);
                new Thread(() =>
                {
                    Thread.Sleep(100);
                    isLock = false;
                }).Start();
            }

            CheckProjectTypeForm.b.action?.Invoke(BaseData.ProjectTypeMessage ?? (0, "", 0));

            txt_address.Text = BaseData.Address ?? "";
            txt_Description.Text = BaseData.Description ?? "";
            txt_name.Text = BaseData.Name ?? "";
            if (BaseData.FromDate != DateTime.Parse("0001-01-01"))
            {
                txt_FromDate.Value = BaseData.FromDate;
                txt_ToDate.Value = BaseData.ToDate;
                CheckUsedStaffForm.b.action_checked?.Invoke(BaseData.Staffs ?? []);
            }

        }
        /// <summary>
        /// 初始化数据（设置开始日期）
        /// </summary>
        /// <param name="time"></param>
        public void InitData(DateTime time)
        {
            InitData(0);
            txt_days.Value = BaseData.Days = 1;
            txt_FromDate.Text = (BaseData.FromDate = time).ToString("yyyy-MM-dd");
            Txt_FromDate_ValueChanged(txt_FromDate, new());
        }

        /// <summary>
        /// 判断当前日期是否为休息日
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        private bool Checkrest(DateTime date)
        {
            var ym = date.ToString("yyyy-MM");
            var isrest = new List<DayOfWeek> { DayOfWeek.Sunday, DayOfWeek.Saturday }.Contains(date.DayOfWeek);
            if (!months.Contains(ym))
            {
                months.Add(ym);

                restdays.AddRange(SearchDays(ym));
            }
            if (restdays.Any(it => it.Day == date))
            {
                if (!isrest)
                {
                    return true;
                }
            }
            else if (isrest)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 错误提示信息
        /// </summary>
        /// <param name="msg"></param>
        static void ShowMsg(string msg)
        {
            MessageBox.Show(msg, "提交提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        /// <summary>
        /// 验证当前项目有效性
        /// </summary>
        /// <returns></returns>
        private bool CheckMsg()
        {

            if (BaseData.Staffs == null || BaseData.Staffs.Count <= 0)
            {
                ShowMsg("请选择员工信息");
                return false;
            }
            if (BaseData.ProjectTypeId == 0)
            {
                ShowMsg("请选择项目类型");
                return false;
            }
            if (string.IsNullOrEmpty(BaseData.Name))
            {
                ShowMsg("请输入项目名称");
                return false;
            }
            if (txt_FromDate.Value > txt_ToDate.Value)
            {
                ShowMsg("结束日期不能早于开始日期");
                return false;
            }

            // 判断开始日期是否为休息日
            if (Checkrest(txt_FromDate.Value.Date))
            {
                ShowMsg("开始日期有误，开始日期不能是休息日");
                return false;
            }
            if (Checkrest(txt_ToDate.Value.Date))
            {
                ShowMsg("结束日期不能是休息日");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 保存项目信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Btn_save_Click(object sender, EventArgs e)
        {
            if (!CheckMsg())
            {
                return;
            }

            if (BaseData.Id == 0)
            {
                BaseData.CreateDate = DateTime.Now;

                var _id = ProjectDao.Base.Add(BaseData);

                foreach (var (id, name) in BaseData.Staffs ?? [])
                {
                    ProjectStaffDao.Base.Add(new ProjectStaff
                    {
                        ProjectId = _id,
                        UserId = id,
                        UserName = name,
                    });
                }
            }
            else
            {
                ProjectDao.Base.Update(BaseData, it => new { it.Name, it.ProjectTypeId, it.Address, it.FromDate, it.ToDate, it.Description, it.RestDate });
                ProjectStaffDao.Base.Delete(it => it.ProjectId == BaseData.Id);
                foreach (var (id, name) in BaseData.Staffs ?? [])
                {
                    ProjectStaffDao.Base.Add(new ProjectStaff
                    {
                        ProjectId = BaseData.Id,
                        UserId = id,
                        UserName = name,
                    });
                }
            }
            MessageBox.Show("保存成功");
            ok_action?.Invoke();
            Close();
        }
        /// <summary>
        /// 选择员工信息弹窗事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Lb_users_Click(object sender, EventArgs e)
        {
            CheckUsedStaffForm.b.GetStaffByStartEnd(BaseData.FromDate, BaseData.ToDate, BaseData.Id);
            CheckUsedStaffForm.b.GetProposeStaffByStartEnd(BaseData.FromDate, BaseData.ToDate);

            CheckUsedStaffForm.b.ShowDialog();
        }

        /// <summary>
        /// 通过年月获取休息日
        /// </summary>
        /// <param name="str">yyyy-MM格式</param>
        /// <returns></returns>
        static List<RestDay> SearchDays(string str) =>
            RestDayDao.Base.FindAll(it => it.Day.ToString("yyyy-MM") == str);
        /// <summary>
        /// 计算开始结束日期
        /// </summary>
        private void CalcTimes()
        {
            if (isLock) return;
            if (!isEdit)
            {
                txt_ToDate.Value = BaseData.ToDate;
                //txt_RestDate.Text = BaseData.RestDate;
                return;
            }
            if (BaseData.ProjectTypeMessage == null || BaseData.Staffs == null || !BaseData.ProjectTypeMessage.HasValue) return;

            var startTime = txt_FromDate.Value.Date;
            var endTime = startTime.AddDays(BaseData.Days - 1);
            if (endTime < startTime) endTime = startTime;
            //开始计算休息日
            days = [];
            for (var date = startTime; date <= endTime; date = date.AddDays(1))
            {
                var ym = date.ToString("yyyy-MM");
                var isrest = new List<DayOfWeek> { 0, DayOfWeek.Saturday }.Contains(date.DayOfWeek);
                // 如果当前月份已经计算过
                if (months.Contains(ym))
                {

                    // 如果休息日里包含当前日期
                    if (restdays.Any(it => it.Day == date))
                    {
                        // 如果是周末 结束日期减一（周末为上班时间）
                        if (isrest)
                        {
                            //endTime = endTime.AddDays(-1);
                        }
                        else
                        {
                            endTime = endTime.AddDays(1);
                            days.Add(date.ToString("yyyy-MM-dd"));
                        }
                    }
                    else if (isrest)
                    {
                        endTime = endTime.AddDays(1);
                        days.Add(date.ToString("yyyy-MM-dd"));
                    }
                }
                else
                {
                    restdays.AddRange(SearchDays(ym));
                    months.Add(ym);
                    date = date.AddDays(-1);
                }
            }
            BaseData.RestDate = string.Join("、", days);

            txt_ToDate.Value = endTime;
        }

        private void Txt_FromDate_ValueChanged(object sender, EventArgs e)
        {
            void act()
            {
                CalcTimes();
                BaseData.FromDate = txt_FromDate.Value.Date;
                BaseData.ToDate = txt_ToDate.Value.Date;
                if (isEdit)
                {
                    BaseData.Staffs?.Clear();
                    BaseData.StaffsList?.Clear();
                    lb_users.Text = "";
                }
            };
            if (Checkrest(txt_FromDate.Value.Date))
            {
                ShowMsg("开始日期不能是休息日");
                txt_FromDate.Value = BaseData.FromDate;
                act();
                return;
            }
            act();
        }

        private void Txt_address_TextChanged(object sender, EventArgs e)
        {
            BaseData.Address = txt_address.Text;
        }

        private void Txt_name_TextChanged(object sender, EventArgs e)
        {
            BaseData.Name = txt_name.Text;
        }

        private void Txt_ToDate_ValueChanged(object sender, EventArgs e)
        {
            BaseData.ToDate = txt_ToDate.Value;
            if (isEdit)
            {
                BaseData.Staffs?.Clear();
                BaseData.StaffsList?.Clear();
                lb_users.Text = "";
            }
        }

        private void Txt_Description_TextChanged(object sender, EventArgs e)
        {
            BaseData.Description = txt_Description.Text;
        }

        private void AddProjectForm_Shown(object sender, EventArgs e)
        {
            restdays = [];
            months = [];
            days = [];
            if (!isEdit)
            {
                Text = "浏览项目信息";
            }
            Controls.Cast<Control>().Where(it => it.Name.StartsWith("txt_") || it.Name.StartsWith("lb_")).ToList().ForEach(c =>
            {
                c.Enabled = isEdit;
            });
            btn_save.Enabled = isEdit;
            //if (isEdit)
            //{
            //    _project_types = ProjectTypeDao.Base.FindAll(it => true).Select(it => (it.Id, it.Name ?? "")).ToList();
            //    txt_type.Items.Clear();
            //    txt_type.Items.AddRange(_project_types.Select(it => it.name).ToArray());
            //}
        }

        private void Txt_days_TextChanged(object sender, EventArgs e)
        {
            BaseData.Days = Convert.ToInt32(txt_days.Value);
            CalcTimes();
        }

        private void Txt_type_TextChanged(object sender, EventArgs e)
        {
            BaseData.ProjectTypeId = _project_types[txt_type.SelectedIndex].id;
        }
    }
}
